/**
 *******************************************************************************
 * @file  template/source/main.c
 * @brief Main program template for the Device Driver Library.
 @verbatim
   Change Logs:
   Date             Author          Notes
   2024-01-15       CDT             First version
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by XHSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "main.h"

#include "usr_adc_handle.h"
#include "usr_buck_boost_ctrl.h"
#include "usr_hrpwm_handle.h"
#include "usr_mos_dri_boost.h"
#include "btn/mcu_button.h"
#include "usr_ec11.h"
#include "usr_lcd.h"
#include "ev_hc32f334_lqfp64_24cxx.h"
#include "usr_uart.h"
#include "usr_pd_i2c.h"
#include "usr_compare.h"
#include "usr_ntc.h"
#include "usr_display_handle.h"
#include "usr_input_handle.h"

UsrMainDatT main_dat;

// void buck_boost_hrpwm_init(void);

/**
 * @brief  Set XTAL as system clock source.
 * @param  None
 * @retval None
 */
static void SystemClockConfig(void) {
    stc_clock_xtal_init_t stcXtalInit;
    stc_clock_pll_init_t stcPLLHInit;

    /* PCLK0, HCLK  Max 120MHz */
    /* PCLK1, PCLK2, PCLK3, PCLK4 Max 60MHz */
    CLK_SetClockDiv(CLK_BUS_CLK_ALL, (CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV2 | CLK_PCLK3_DIV2 | CLK_PCLK4_DIV2 | CLK_HCLK_DIV1));

    GPIO_AnalogCmd(BSP_XTAL_PORT, BSP_XTAL_IN_PIN | BSP_XTAL_OUT_PIN, ENABLE);
    (void)CLK_XtalStructInit(&stcXtalInit);
    /* Config Xtal and enable Xtal */
    stcXtalInit.u8Mode = CLK_XTAL_MD_OSC;
    stcXtalInit.u8Drv = CLK_XTAL_DRV_ULOW;
    stcXtalInit.u8State = CLK_XTAL_ON;
    stcXtalInit.u8StableTime = CLK_XTAL_STB_2MS;
    (void)CLK_XtalInit(&stcXtalInit);

    (void)CLK_PLLStructInit(&stcPLLHInit);
    /* VCO = (8/1)*60 = 480MHz*/
    stcPLLHInit.u8PLLState = CLK_PLL_ON;
    stcPLLHInit.PLLCFGR = 0UL;
    stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLN = 60UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL;
    (void)CLK_PLLInit(&stcPLLHInit);

    /* 2 cycles for 100 ~ 120MHz */
    (void)EFM_SetWaitCycle(EFM_WAIT_CYCLE2);
    /* 2 cycles for 100 ~ 120MHz */
    GPIO_SetReadWaitCycle(GPIO_RD_WAIT2);
    CLK_SetSysClockSrc(CLK_SYSCLK_SRC_PLL);

    // /* Reset cache ram */
    EFM_CacheRamReset(ENABLE);
    EFM_CacheRamReset(DISABLE);
    /* Enable cache */
    EFM_PrefetchCmd(ENABLE);
    EFM_DCacheCmd(ENABLE);
    EFM_ICacheCmd(ENABLE);
}

/**
 * @brief  USART RX IRQ callback
 * @param  None
 * @retval None
 */
void USART_RxFull_IrqCallback(void) {
    uint8_t u8Data = (uint8_t)USART_ReadData(BSP_PRINTF_DEVICE);
    // main_dat.rx_dat_buf[main_dat.rx_cnt++] = u8Data;
}

/**
 * @brief  SysTick interrupt handler function.
 * @param  None
 * @retval None
 */
extern uint32_t m_u32TickStep;
extern __IO uint32_t m_u32TickCount;

RAM_FUNC void SysTick_Handler(void) {
    // SysTick_IncTick();
    m_u32TickCount += m_u32TickStep;
    main_dat.usr_tick++;
    __DSB(); /* Arm Errata 838869 */
}
/**
 * @brief  Software interrupt Ch.31 callback function
 *         IRQ No.31 in Global is used for it
 * @param  None
 * @retval None
 */
void EXTINT15_SWINT31_Handler(void) {
    // BSP_LED_Toggle(LED_BLUE);
    INTC_SWIntCmd(SWINT_CH31, DISABLE);
    
    __DSB(); /* Arm Errata 838869 */
}

/**
 * @brief  DMA IRQ handler.
 * @param  None
 * @retval None
 */
extern int adc_finished_flg;
RAM_FUNC void DMA_IRQ_HANDLER(void) {
    if (DMA_GetTransCompleteStatus(DMA_UNIT, DMA_INT_FLAG) == SET) {
        DMA_ClearTransCompleteStatus(DMA_UNIT, DMA_INT_FLAG);
        adc_finished_flg=1;
    }
    if (DMA_GetTransCompleteStatus(DMA_UNIT, DMA_FLAG_BTC_CH1) == SET) {
        DMA_ClearTransCompleteStatus(DMA_UNIT, DMA_FLAG_BTC_CH1);
    }
    if (DMA_GetTransCompleteStatus(DMA_UNIT, DMA_FLAG_BTC_CH2) == SET) {
        DMA_ClearTransCompleteStatus(DMA_UNIT, DMA_FLAG_BTC_CH2);
        // adc_finished_flg = 1;
        // DDL_Printf("t\n");
    }
    __DSB(); /* Arm Errata 838869 */
}

void buck_boost_data_init(void){
    
    HRPWM_CmpDat_T cmp_dat;

    // usr_buck_boost_pid_init(&main_dat.buck_boost);
    usr_buck_boost_int_pid_init(&main_dat.buck_boost);
    main_dat.buck_boost.buck_period = hrpwm_set_pwm_out_freq(HRPWM_BST_PWM_UNIT, HRPWM_DEFAULT_FREQ);
    main_dat.buck_boost.boost_period = hrpwm_set_pwm_out_freq(HRPWM_BUCK_PWM_UNIT, HRPWM_DEFAULT_FREQ);
    
    cmp_dat = hrpwm_buck_get_cmp_value(0, main_dat.buck_boost.buck_period, BUCK_MINI_DUTY_CYCLE);
    hrpwm_set_cmp_values(HRPWM_BUCK_PWM_UNIT, cmp_dat);

    cmp_dat = hrpwm_boost_get_cmp_value(cmp_dat.cmp_a_value, main_dat.buck_boost.boost_period, BUCK_MINI_DUTY_CYCLE);
    hrpwm_set_cmp_values(HRPWM_BST_PWM_UNIT, cmp_dat);
}

BuckBoostErrInfor buck_boost_error_handle(int vi_adc, int vo_adc, int curr_adc){
    uint16_t i_uvp_threshold = INPUT_UVP_THRESHOLD;

    BuckBoostErrInfor error_infor={0};
    if(vi_adc < i_uvp_threshold){
        error_infor.input_uvp_err = 1;
        disable_output_handle("OFF-UVP"); 
    }else if(vi_adc > INPUT_OVP_THRESHOLD){
        error_infor.input_ovp_err = 1;    
    }

    return error_infor;
}

// void buck_boost_hrpwm_init(void){
//     LL_PERIPH_WE(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM);
//     // DDL_Printf("TEST22!\n");
//     usr_buck_hrpwm_init();
//     usr_boost_hrpwm_init();
//     /* MCU Peripheral registers write protected. */
//     LL_PERIPH_WP(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM);
// }

void usr_cfg_dats_init(void){

    
    if(LL_OK == BSP_24CXX_Read(CFG_SAVE_ADDR,(uint8_t *)&main_dat.usr_cfg,sizeof(main_dat.usr_cfg))){
        if(main_dat.usr_cfg.cfg_vo > CFG_VO_MAX || main_dat.usr_cfg.cfg_vo < CFG_VO_MIN){
            main_dat.usr_cfg.cfg_vo = CFG_VO_DEFAULT;
        }
        if(main_dat.usr_cfg.cfg_io > CFG_IO_MAX || main_dat.usr_cfg.cfg_io < CFG_IO_MIN){
            main_dat.usr_cfg.cfg_io = CFG_IO_DEFAULT;
        }
    }else{
       DDL_Printf("read Usr cfg data failed\n"); 
       main_dat.usr_cfg.cfg_vo = CFG_VO_DEFAULT;
       main_dat.usr_cfg.cfg_io = CFG_IO_DEFAULT;
    }

}


RAM_FUNC void put_value_in_cycle_buf(uint16_t *p_buf, uint16_t in_adc, uint16_t *put_indx,uint16_t max_buf_len){

    if(p_buf == NULL )return;

    p_buf[*put_indx] = in_adc;
    (*put_indx)++;
    (*put_indx) %= max_buf_len;
}
RAM_FUNC uint16_t get_adc_value_by_rec_buf(uint16_t *p_buf,uint16_t max_buf_len){
    uint32_t sum=0;
    uint16_t ret;

    for(int i=0; i<max_buf_len; i++){
        sum += p_buf[i];
    }

    ret = sum / max_buf_len;

    return ret;
}


/**
 * @brief  over current CMP interrupt call back
 * @param  None
 * @retval None
 */
void CMP1_Handler(void) {
    if (SET == CMP_GetStatus(CMP_TEST_UNIT)) {
        main_dat.ovcp_flg = 1;
        DDL_Printf("T-C-INT\n");
    } else {
        DDL_Printf("T-C-INT-0\n");
    }

    __DSB(); /* Arm Errata 838869 */
}

/********************************************************************** */

/********************************************************************* */
/**
 * @brief  Main function of template project
 * @param  None
 * @retval int32_t return value, if needed
 */
RAM_FUNC int32_t main(void) {
    
    uint32_t local_tick = 0;
    uint16_t vin_indx=0;
    uint16_t vin_adc;
    uint16_t vin_adc_buf[VIN_ADC_MAX_BUF];
    uint16_t vout_adc_buf[VIN_ADC_MAX_BUF];
    uint16_t io_adc_buf[VIN_ADC_MAX_BUF];
    uint16_t vout_adc;
    uint16_t io_adc;
    #if BUCK_BOOST_CC_FUNCTION_ENABLE
    CV_CC_FLAGE_T cc_cv_flage = CV_ACTIVE;
    #endif
    int board_temp=0;
    
    /* MCU Peripheral registers write unprotected. */
    LL_PERIPH_WE(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM);
    stc_gpio_init_t stcGpioInit;

    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16PinState = PIN_STAT_RST;
    stcGpioInit.u16PinDir = PIN_DIR_OUT;
    (void)GPIO_Init(CAP_DISCARGE_CTL_PORT, CAP_DISCARGE_CTL_PIN, &stcGpioInit);

    (void)GPIO_Init(GPIO_PORT_A, GPIO_PIN_15, &stcGpioInit);

    GPIO_SetDebugPort(GPIO_PIN_DEBUG, DISABLE);
    /* System clock config */
    SystemClockConfig();
    /* SysTick configuration */
    (void)SysTick_Init(1000U);
    /* Initializes UART for debug printing. Baudrate is 115200. */
    DDL_PrintfInit(BSP_PRINTF_DEVICE, BSP_PRINTF_BAUDRATE, BSP_PRINTF_Preinit);
    // DDL_Printf("TEST22!\n");
    usr_buck_hrpwm_init();
    usr_boost_hrpwm_init();

    /* Configures ADC. */
    AdcConfig();
    Adc3_Config();
    Adc2_Config();
    // AdcInitConfig();
    // usr_ntc_handle_init();    
    pid_process_period_timer_init();

    mcu_btn_init(usr_btn_msg_cb_handle);   
    // LCD_SPI_Config();
    
    ec11_rec_io_init();
    if (LL_OK != BSP_24CXX_Init()) {
       DDL_Printf("init 24cxx failed\n");
    }

    usr_uart_init();
    // usr_compare_init();
    usb_pd_int_gpio_init();
    /* MCU Peripheral registers write protected. */
    LL_PERIPH_WP(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM);
    DDL_Printf(
        "Author:黑马小乌龟(HeiMaXiaoWuGui)\n\
                Date:2025-07-15\n\
                Prj-Name:Buck-Boost\n\
                FW-Version:%s\n",
        FW_VERSION);
    memset(&main_dat, 0, sizeof(main_dat));

    // lcd_init();
    // lcd_test_fun();
    
    buck_boost_data_init();
    usr_cfg_dats_init();

    usr_set_output_current(&main_dat.buck_boost,main_dat.usr_cfg.cfg_io/*mA*/);    
    usr_set_output_vol(&main_dat.buck_boost, main_dat.usr_cfg.cfg_vo);
    main_dat.buck_boost.wk_mode = BUCK_W_MODE;
    main_dat.usr_tick = 1;
    main_dat.lcd_flush_cnt = 1;
    
    HRPWM_SWSyncStart(HRPWM_BUCK_PWM_UNIT_ID|HRPWM_BST_PWM_UNIT_ID);
     
    CAP_DISCARGE_CTL(CAP_DISCARGE_ON);    
    GPIO_ResetPins(GPIO_PORT_A, GPIO_PIN_15);
    
    DDL_DelayMS(20);
    int32_t ret = usr_PD_I2C_Read(0,&main_dat.pd_ver,1);
    if(ret == LL_OK){
        DDL_Printf("PD FW ver%x:V%d,%d\n",main_dat.pd_ver,(main_dat.pd_ver>>4),(main_dat.pd_ver&0x0f));
    }
    
    // stc_clock_freq_t pstcClockFreq;
    
    // if(CLK_GetClockFreq(&pstcClockFreq)==LL_OK){
    //     DDL_Printf("SysclkFreq:%lu\nHclkFreq:%lu\nPclk0Freq:%lu\nPclk1Freq:%lu\nPclk2Freq:%lu\nPclk3Freq:%lu\nPclk4Freq:%lu\n",
    //                 pstcClockFreq.u32SysclkFreq,
    //                 pstcClockFreq.u32HclkFreq,  
    //                 pstcClockFreq.u32Pclk0Freq, 
    //                 pstcClockFreq.u32Pclk1Freq, 
    //                 pstcClockFreq.u32Pclk2Freq, 
    //                 pstcClockFreq.u32Pclk3Freq, 
    //                 pstcClockFreq.u32Pclk4Freq);         
    // }

    for (;;) {
        if (adc_finished_flg) {
            adc_finished_flg = 0;
            // GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_15);
            vin_adc = m_au16AdcValue_adc2[2];
            // DDL_Printf("1:%d,2:%d,3:%d",m_au16AdcValue_adc2[0],m_au16AdcValue_adc2[1],m_au16AdcValue_adc2[2]);
            vout_adc = m_au16AdcValue[0];
            io_adc = m_au16AdcValue_adc3[0];
#if 1
            // usr_buck_boost_work_mode_handle(&main_dat.buck_boost, vin_adc, vout_adc, io_adc);
            usr_buck_boost_work_mode_handle_int(&main_dat.buck_boost, vin_adc, vout_adc, io_adc);
        /*****************************************软起动处理开始*********************************************************/
            if (main_dat.soft_up_en) { 
                main_dat.soft_up_cnt++;
                main_dat.soft_up_cnt = 0;
                // main_dat.soft_vo += main_dat.soft_vo * 0.02f;  // mV 实现开始增长步进小，越往后增长步进越大
                // 计算目标值与输入值的差值
                float diff = main_dat.usr_cfg.cfg_vo - ADC_CAL_VOL(vin_adc);

                // 根据差值大小动态调整步进系数
                float step_factor;
                if (diff > 0) {
                    // 差值越大，步进越小（使用反比例关系）
                    step_factor = 0.015f / (1.0f + diff * 0.0005f);  // 0.0005f是衰减系数，可调整，系数越大调整越慢
                } else {
                    // 如果cfg_vo <= v_in，使用基础步进
                    step_factor = 0.015f;
                }
                // 应用缓启动更新
                main_dat.soft_vo += (main_dat.usr_cfg.cfg_vo - main_dat.soft_vo) * step_factor;  //  mV 实现开始增长步进大，越往后增长步进越小
                if (main_dat.soft_vo >= main_dat.usr_cfg.cfg_vo) {
                    main_dat.soft_up_en = 0;
                    main_dat.soft_vo = main_dat.usr_cfg.cfg_vo;
                }
                usr_set_output_vol(&main_dat.buck_boost, main_dat.soft_vo);
        /*****************************************软起动处理结束*********************************************************/
            }
#endif
            vin_adc_buf[vin_indx] = vin_adc;
            vout_adc_buf[vin_indx] = vout_adc;
            io_adc_buf[vin_indx] = io_adc;
            vin_indx++;
            vin_indx %= VIN_ADC_MAX_BUF;
#if !BUCK_BOOST_CC_FUNCTION_ENABLE
            if (main_dat.ps_out == PS_OUT_ENABLE) {
                if (get_adc_value_by_rec_buf(io_adc_buf, VIN_ADC_MAX_BUF) > main_dat.buck_boost.ref_io) { /*目前限流功能没有做好，限流状态下会烧MOS管，暂时将限流做成过流保护*/
                    main_dat.ps_out = PS_OUT_DISABLE;
                    main_dat.ps_delay_to_close_hrpwm = 100u;
                    // // usr_set_output_vol(&main_dat.buck_boost, CFG_VO_MIN);
                    // lcd_ascii_str_dis(2,64,ascii_16x16_font,"OFF ");
                    HRPWM_IDLE_EnterImmediate(HRPWM_BST_PWM_SYNC_UNIT, HRPWM_SW_SYNC_CH_ALL);
                    HRPWM_IDLE_EnterImmediate(HRPWM_BUCK_PWM_SYNC_UNIT, HRPWM_SW_SYNC_CH_ALL);
                    usr_uart_send_a_msg(OUTPUT_STATE_CMD, "OCP-OFF");
                }
            }
#endif
            // GPIO_ResetPins(GPIO_PORT_A, GPIO_PIN_15);
        }

        if (main_dat.ovcp_flg) { /*过流保护发生*/
            main_dat.ovcp_flg = 0;
            // DDL_Printf("ovcp!!!\n");
        }

        if (local_tick != main_dat.usr_tick) {
            local_tick = main_dat.usr_tick;
            usr_ec11_debounce_handle();
            io_key_task_handle();
            mcu_button_loop(1 /*mS*/);
            rotate_encoder_handle();

            if (main_dat.cfg_active_timeout) {
                main_dat.cfg_active_timeout--;
                if (main_dat.cfg_active_timeout == 0) {
                    main_dat.cfg_state = CFG_MENU_NULL;
                    // usr_cfg_item_display(main_dat.cfg_state, main_dat.usr_cfg.cfg_vo, main_dat.usr_cfg.cfg_io);
                    usr_cfg_item_active_handle(main_dat.cfg_state);
                }
            }
            if (main_dat.ps_delay_to_close_hrpwm) {
                main_dat.ps_delay_to_close_hrpwm--;
                if (main_dat.ps_delay_to_close_hrpwm == 0) {
                    DDL_Printf("HRPWM-ENTRY-IDLE\n");
                    CAP_DISCARGE_CTL(CAP_DISCARGE_ON);
                    // usr_hrpwm_stop_all();
                }
            }
            if (main_dat.usr_cfg_save_timeout) {
                main_dat.usr_cfg_save_timeout--;
                if (!main_dat.usr_cfg_save_timeout) {
                    BSP_24CXX_Write(CFG_SAVE_ADDR, (uint8_t *)&main_dat.usr_cfg, sizeof(main_dat.usr_cfg));
                }
            }
            if (main_dat.usr_tick % 500 == 0) {
                update_in_out_information(get_adc_value_by_rec_buf(vin_adc_buf, VIN_ADC_MAX_BUF), get_adc_value_by_rec_buf(vout_adc_buf, VIN_ADC_MAX_BUF),
                                          get_adc_value_by_rec_buf(io_adc_buf, VIN_ADC_MAX_BUF));                         

                usb_pd_information_handle(0);    
                                          #if BUCK_BOOST_CC_FUNCTION_ENABLE
                if(cc_cv_flage != main_dat.cv_cc_flg){
                    main_dat.cv_cc_flg = cc_cv_flage;
                    if(main_dat.cv_cc_flg == CV_ACTIVE){
                        usr_uart_send_a_msg(OUTPUT_STATE_CMD, "CV");
                    }else{
                        usr_uart_send_a_msg(OUTPUT_STATE_CMD, "CC");
                    }
                }
#endif
            }

            if (main_dat.usr_tick % 3000 == 0) {
                
                if (ntc_adc_polling(&board_temp) == 0) {
                    // DDL_Printf("board temp:%d°C\n", board_temp);
                    char tmp[10];
                    sprintf(tmp, "%d°C", board_temp);
                    usr_uart_send_a_msg(BOARD_TEMPERATUR, tmp);
                    if(board_temp > OVER_TEMPERATURE_PROTECT_THRESOLD){ /*over temperature protect*/
                        main_dat.ps_out = PS_OUT_DISABLE;
                        main_dat.ps_delay_to_close_hrpwm = 100u;
                        // // usr_set_output_vol(&main_dat.buck_boost, CFG_VO_MIN);
                        // lcd_ascii_str_dis(2,64,ascii_16x16_font,"OFF ");
                        HRPWM_IDLE_EnterImmediate(HRPWM_BST_PWM_SYNC_UNIT, HRPWM_SW_SYNC_CH_ALL);
                        HRPWM_IDLE_EnterImmediate(HRPWM_BUCK_PWM_SYNC_UNIT, HRPWM_SW_SYNC_CH_ALL);

#if LCD_PANEL_ENABLE
                        disable_output_handle("OFF ");
#else
                        usr_uart_send_a_msg(OUTPUT_STATE_CMD, "OTP-OFF");
#endif
                    }
                }

                // if (SET == CMP_GetStatus(CMP_TEST_UNIT)) {
                //     // DDL_Printf("comp p>m \n");
                // } else {
                //     // DDL_Printf("comp p<m \n");
                // }
            }

            if (main_dat.usr_tick % 10 == 0) {
                usr_uart_msg_process();
                usr_uart_msg_pool_handle();
            }
        }
    }
}

/**
 * @}
 */

/**
 * @}
 */

/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
